/**
 * 基于 ESP32 LEDC 模块实现的 PWM 发生器驱动
 */
#pragma once

#include "std_type.h"
#include "esp_err.h"
#include "driver/ledc.h"

#ifdef __cplusplus
extern "C" {
#endif


typedef void* pwm_handle_t;

/**
 * 基于 4 个 LEDC HIGH_SPEED Timer 的 4~7 通道实现的 4 个 PWM 发生器
 * @attention 注意如果同时其它驱动程序也使用了这些定时器和通道，会造成冲突，产生不可预料的行为！
 */
extern const pwm_handle_t PWM0;
extern const pwm_handle_t PWM1;
extern const pwm_handle_t PWM2;
extern const pwm_handle_t PWM3;

/**
 * 当指定的 PWM 波形数量完成后调用的中断回调函数
 * @return 是否继续(默认情况下，如果没有回调函数，则播放完成后自动停止)
 * @attention 注意：此函数是在 ETS_LEDC_INTR_SOURCE 中断中调用的，所以请遵守中断函数编写注意事项！
 */
typedef bool (*FUNC_pwmIsrCallback)(void *cookie);

/// 永远播放
#define PWM_COUNT_MAX 		0xFFFFFFFF
#define PWM_COUNT_FOREVER 	PWM_COUNT_MAX

/// 在指定时间内会产生多少个 PWM 波形
#define PWM_COUNT_DURING_TIME_MS(freq, ms) ((freq)*(ms)/1000 + 1)

/**
 * 启动 PWM 生成
 * @param pwm 使用的 PWM 通道
 * @param freq 频率(Hz)
 * @param dutyRatio 占空比(%)，duty 时间默认输出高电平
 * @param count PWM 波形数量(用于控制持续时间)，如果等于 PWM_COUNT_MAX 则表示永远不自动停止
 * @param outputPin PWM 输出引脚，如果 <0 则不输出，但其绝对值应是正确的引脚编号
 * @param callback 当指定的 PWM 波形数量完成后调用的中断回调函数
 * @param cookie callback 的 cookie
 * @return 错误码
 */
esp_err_t PWM_start(pwm_handle_t pwm, uint32_t freq, int dutyRatio, uint32_t count, int outputPin, FUNC_pwmIsrCallback callback, void *cookie);

/**
 * 停止指定 PWM 通道的 PWM 生成
 * @param pwm 使用的 PWM 通道
 */
void PWM_stop(pwm_handle_t pwm);

/**
 * 启动并继续 stop 前的记数
 * @param pwm 使用的 PWM 通道
 */
void PWM_continue(pwm_handle_t pwm);

/**
 * 启动并重新开始记数
 * @param pwm 使用的 PWM 通道
 */
void PWM_restart(pwm_handle_t pwm);


#ifdef __cplusplus
}
#endif
